﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SmlEngine.Graphics
{
    [Obsolete] // (cel) I'm not sure it's obsolete any more, maybe remove this attribute?
    public static class GraphicsHelper
    {
        /* public static Texture2D Crop(this Texture2D source, Rectangle area)
        {
            if (source == null)
                return null;

            Texture2D cropped = new Texture2D(source.GraphicsDevice, area.Width, area.Height);
            Color[] data = new Color[source.Width * source.Height];
            Color[] cropData = new Color[cropped.Width * cropped.Height];

            source.GetData(data);

            int index = 0;
            for (int y = area.Y; y < area.Y + area.Height; y++)
            {
                for (int x = area.X; x < area.X + area.Width; x++)
                {
                    cropData[index] = data[x + (y * source.Width)];
                    index++;
                }
            }

            cropped.SetData(cropData);

            return cropped;
        } */

        /// <summary>
        /// Crops a texture.
        /// </summary>
        /// <param name="area">The final area of the texture.</param>
        /// <returns>The cropped texture.</returns>
        public static Texture2D Crop(this Texture2D texture, Rectangle area)
        {
            if (texture == null)
                return null;

            RenderTarget2D target = new RenderTarget2D(texture.GraphicsDevice, area.Width, area.Height);

            SpriteBatch spriteBatch = new SpriteBatch(texture.GraphicsDevice);

            texture.GraphicsDevice.SetRenderTarget(target);
            texture.GraphicsDevice.Clear(Color.Transparent);

            spriteBatch.Begin();
            spriteBatch.Draw(texture, Vector2.Zero, area, Color.White);
            spriteBatch.End();

            texture.GraphicsDevice.SetRenderTarget(null);

            return target;
        }

        /// <summary>
        /// Copies one texture into another.
        /// </summary>
        /// <param name="graphicsDevice">The GraphicsDevice to use.</param>
        /// <param name="image">The base texture.</param>
        /// <param name="source">The area to copy.</param>
        /// <returns>The copied texture.</returns>
        public static RenderTarget2D CopyTexture2D(GraphicsDevice graphicsDevice, Texture2D image, Rectangle source)
        {
            Rectangle destination = new Rectangle(0, 0, source.Width, source.Height);

            // Create a new render target the size of the cropping region.
            RenderTarget2D target = new RenderTarget2D(graphicsDevice, source.Width, source.Height); //(gd, source.Width, source.Height, 1, SurfaceFormat.Color);

            // Make it the current render target.
            graphicsDevice.SetRenderTarget(target); //(0, target);

            // Render the selected portion of the source image into the render target.
            SpriteBatch sb = new SpriteBatch(graphicsDevice);
            sb.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);//(Sp, SpriteSortMode.Immediate, SaveStateMode.None);
            sb.Draw(image, destination, source, Color.White);
            sb.End();

            // Resolve the render target.  This copies the target's buffer into a texture buffer.
            graphicsDevice.SetRenderTarget(null);

            // Finally, return the target.
            return target;
        }

        /// <summary>
        /// Overlays one Texture2D on top of another.
        /// </summary>
        /// <param name="background">The texture to overlay on to.</param>
        /// <param name="foreground">The texture which to overlay.</param>
        /// <returns>The final texture.</returns>
        public static Texture2D Overlay(Texture2D background, Texture2D foreground)
        {
            if (background == null && foreground != null) return foreground;
            else if (foreground == null && background != null) return background;
            else if (foreground == null && background == null) return null;

            if (foreground.GraphicsDevice != background.GraphicsDevice) throw new ArgumentException("The textures do not have the same GraphicsDevice.  {SmlEngine.Graphics.GraphicsHelper.Overlay}");

            RenderTarget2D target = new RenderTarget2D(background.GraphicsDevice, background.Width, background.Height);

            SpriteBatch spriteBatch = new SpriteBatch(background.GraphicsDevice);

            background.GraphicsDevice.SetRenderTarget(target);
            background.GraphicsDevice.Clear(Color.Transparent);

            spriteBatch.Begin();
            spriteBatch.Draw(background, Vector2.Zero, Color.White);
            spriteBatch.Draw(foreground, Vector2.Zero, Color.White);
            spriteBatch.End();

            background.GraphicsDevice.SetRenderTarget(null);
            return target;
        }

        public static Texture2D Merge(GraphicsDevice Graphics, Dictionary<Vector2, Texture2D> textures, int width, int height)
        {
            if (textures.Count == 0) return null;

            RenderTarget2D target = new RenderTarget2D(Graphics, width, height);
            SpriteBatch spriteBatch = new SpriteBatch(Graphics);

            Graphics.SetRenderTarget(target);
            Graphics.Clear(Color.Transparent);

            spriteBatch.Begin();
            foreach (var kvp in textures)
            {
                spriteBatch.Draw(kvp.Value, kvp.Key, Color.White);
            }
            spriteBatch.End();

            Graphics.SetRenderTarget(null);
            return target;
        }

        /// <summary>
        /// Determines whether a given path is a resource name from the content pipeline or a filename.
        /// </summary>
        /// <param name="path">The path to check.</param>
        /// <returns>Whether or not the path is from the content pipeline.</returns>
        public static bool IsContentPath(string path)
        {
            return !path.Contains(".png"); // Yeah, it's hardcoded, but for our purposes it should work fine.
        }

        #region Unused

        /* public static Rectangle GetCropRectangle(Sprite sprite)
        {
            return new Rectangle((int)(sprite.CurrentFrame.X) * (int)sprite.Size.X, (int)(sprite.CurrentFrame.Y) * (int)sprite.Size.Y, (int)sprite.Size.X, (int)sprite.Size.Y);
        }


        public static System.Drawing.Image TextureToImage(Texture2D texture)
        {
            if (texture == null)
            {
                return null;
            }

            if (texture.IsDisposed)
            {
                return null;
            }

            //Memory stream to store the bitmap data.
            MemoryStream ms = new MemoryStream();

            //Save the texture to the stream.
            texture.SaveAsPng(ms, texture.Width, texture.Height);

            //Seek the beginning of the stream.
            ms.Seek(0, SeekOrigin.Begin);

            //Create an image from a stream.
            System.Drawing.Image bmp2 = System.Drawing.Bitmap.FromStream(ms);

            //Close the stream, we nolonger need it.
            ms.Close();
            ms = null;
            return bmp2;
        }

        public static void ImageToTexture(System.Drawing.Image image,
                                         GraphicsDevice graphics,
                                         ref Texture2D texture)
        {
            if (image == null)
            {
                return;
            }

            if (texture == null || texture.IsDisposed ||
                texture.Width != image.Width ||
                texture.Height != image.Height ||
                texture.Format != SurfaceFormat.Color)
            {
                if (texture != null && !texture.IsDisposed)
                {
                    texture.Dispose();
                }

                texture = new Texture2D(graphics, image.Width, image.Height, false, SurfaceFormat.Color);
            }
            else
            {
                for (int i = 0; i < 16; i++)
                {
                    if (graphics.Textures[i] == texture)
                    {
                        graphics.Textures[i] = null;
                        break;
                    }
                }
            }

            //Memory stream to store the bitmap data.
            MemoryStream ms = new MemoryStream();

            //Save to that memory stream.
            image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

            //Go to the beginning of the memory stream.
            ms.Seek(0, SeekOrigin.Begin);

            //Fill the texture.
            texture = Texture2D.FromStream(graphics, ms, image.Width, image.Height, false);

            //Close the stream.
            ms.Close();
            ms = null;
        }

        */

        #endregion
    }
}
